#!/usr/bin/env python
from time import strftime
import os

PASSWORDCODE_OFFSET = 0x00000042
PASSWORDCODE_SIZE = 40
PASSWORDCODE_XORMAP = (0x55,0xEC,0x8E,0x9C,0x15,0x28,0xC0,0x8A,0x87,0x7B,0x26,0xDF,0xA4,0x13,0x1C,0xB1,0xE7,0x79,0x41,0x7C)

class Decryptor2000:
    def __init__(self,path):
        self.DBVersion = "4.0"
        self.Signature = "Standard Jet DB"
        self.szMessage = ""
        self.path = ""
        self.SetDBPath(path)
    
    def PostNotification(self,szMessage):
        self.szMessage += ("[" + strftime("%b %d,%Y %H:%M:%S") + "] " + szMessage + "\r\n")
        
    def FlushNotification(self):
        print self.szMessage
        
    def SetDBPath(self,path):
        self.path = path
        if path != "" : 
            self.PostNotification("Database file specified.")
            
    def GetDBPath(self):
        if(self.path.length != 0):
            print "DATABASE Path: " + self.path + "\r\n"
        else:
            print "DATABASE not specified."
    
    def GetPasswordMultiByte(self):
        path = self.path
        szPasswordMultiByte = ""
        try:
            f = open(path,"r+",PASSWORDCODE_OFFSET + PASSWORDCODE_SIZE)
            f.seek(PASSWORDCODE_OFFSET,os.SEEK_SET)
            szPasswordMultiByte = f.read(PASSWORDCODE_SIZE)
            f.close()
        except IOError:
            self.PostNotification("An IO error occurred when trying to access the database file.")
        
        if(len(szPasswordMultiByte) != 0):
            self.PostNotification("Encrypted password string fetched.")
        else:
            self.PostNotification("Error: encrytped password string cannot be fetched.")
        return szPasswordMultiByte
    
    def GetPasswordHex(self,szPasswordMultiByte):
        i = 0
        szPasswordHex = ""
        for c in szPasswordMultiByte:
            if(i%2 == 0):
                szPasswordHex += c
            i += 1
        
        if(len(szPasswordHex) != 0):
            self.PostNotification("Encrypted password string cleaned.")
        else:
            self.PostNotification("Error: encrypted password cannot be cleaned.")
        return szPasswordHex
        
    def GetPassword(self,szPasswordHex):
        szPassword = ""
        i = 0
        for c in szPasswordHex:
            cPassword = chr(ord(szPasswordHex[i]) ^ PASSWORDCODE_XORMAP[i])
            szPassword += cPassword
            if(ord(cPassword) == 0x00):
                break
            i += 1
        self.PostNotification("Password decrypted.The result is: " + szPassword)
        return szPassword
    
    def Decrypt(self):
        szPasswordMultiByte = self.GetPasswordMultiByte()
        szPasswordHex = self.GetPasswordHex(szPasswordMultiByte)
        szPassword = self.GetPassword(szPasswordHex)
        if(szPassword != ""):
            self.PostNotification("Password successfully decrypted.")
        self.FlushNotification()
    